import _ from 'lodash';
import Number from '../number/index.vue';
import Decorate from '../decorate/index.vue';
import music from '../../unit/music';
import music_gm from '../../unit/music_gm';
import Keyboard from '../keyboard/index.vue';
import { mapState } from 'vuex';
import Logo from '../logo/index.vue';



export default {
  components: {
    Number,
    Decorate,
    Keyboard,
    Logo
  },
  computed: {
    ...mapState(['speed', 'changeCss', 'fixedBlocks', 'ROW_COUNT', 'COL_COUNT', 'MODELS', 'rmRowSum', 'nextModel', 'stop', 'gameplay'])
  },
  data() {
    return {
      step: 22,
      // 变量,当前使用的模型
      currentModel: {},

      // 标记 16 宫格的位置
      currentX: 0,
      currentY: 0,
      // 记录所有块元素位置

      // 定时器
      mInterval: null,
      left: null,
      right: null,
      top: null,
      down: null,
      // gameOver: false 
      time: null,//time用来控制事件的触发
      mov: true,
      droptime: 140,



    };
  },
  watch: {
    rmRowSum(newval, oldval) {
      // 每消除10行加速
      // console.log(newval.join(''));
      if (newval.join('') % 10 === 0 && newval.join('') <= 100 && !this.changeCss) {
        // 500为初始速度，如果要增加初始难度则修改这个500为动态
        this.$store.state.speed = 500 - (50 * (newval.join('') / 10));
      }
      else if (newval.join('') % 10 === 0 && newval.join('') <= 100 && this.changeCss) {
        // 500为初始速度，如果要增加初始难度则修改这个500为动态
        this.$store.state.speed = 500 - (200 * (newval.join('') / 10));
      }

    }
  },
  methods: {
    key() {
      document.addEventListener('keydown', (e) => {
        switch (e.code) {
          case 'ArrowUp':
            this.keyUp();
            break;
          case 'ArrowDown':
            this.keyDown();

            break;
          case 'ArrowLeft':
            this.keyLeft();

            break;

          case 'ArrowRight':
            this.keyRight();

            break;

          case 'Space':
            this.keySpace();

            break;
        }

      });

      // 搭配上面那个取消掉按住键后摇
      // tip:延时是因为系统重复按键的设置，这个是没法避免的，所以你的程序不能这样写，
      // 你按下某个键肯定是希望它一直去做这件事，那你只需要在按下键的时候启动一个定时器，去移动拟的div，
      // 等键盘抬起的时候清除这个定时器就可以了
      // 用else if会有bug
      this.eventCleanTimer();
    },
    move(x, y, state) {  // x,y,是否音效
      // this.$store.commit('gameplay');
      // var activityModelEle = document.getElementsByClassName('square');
      // console.log(activityModelEle);
      // activityModelEle.style.top = parseInt(activityModelEle.style.top || 0) + y * this.step + 'px';
      // activityModelEle.style.left = parseInt(activityModelEle.style.left || 0) + x * this.step + 'px';
      if (this.$store.state.speed == 100000) {
        return;
      }
      if (!this.gameplay) {
        return;
      }

      if (this.isMeet(this.currentX + x, this.currentY + y, this.currentModel)) {
        if (y !== 0) {
          // 模型之间发生了触碰
          this.fixedBottomModel();
        }
        return;
      }
      // 16 宫格在动
      this.currentX += x;
      this.currentY += y;
      if (state) {
        if (this.changeCss) {
          music_gm.move();
        }
        else {

          music.move();
        }
      }

      // 根据16宫格 的位置重新定义块元素
      this.locationBlocks();
    },
    createModel() {

      // 在创建新模型之前，判断游戏是否已经结束了
      if (this.isGameOver()) {
        // 如果游戏已经结束了，那么就不需要再自动降落模型了
        this.gameOver();
        return;
      }

      if (this.changeCss) {
        if (!this.$store.state.flag) {
          return;
        }
      }

      // 当前的模型数据源,判断是否第一次获取
      if (JSON.stringify(this.nextModel) == '{}') {
        this.currentModel = this.MODELS[_.random(0, this.MODELS.length - 1)];
        // this.currentModel = this.MODELS[this.MODELS.length - 1];
      } else {
        this.currentModel = this.nextModel;
      }
      //获得下一个模型      
      this.$store.commit('nextModel');

      // 因为消除一行的动画是异步，所以我们需要创建的时候重新更新一下分数
      this.$store.commit('splitsum');



      // 重新初始化16宫格的位置
      this.currentX = 3;
      this.currentY = -2;
      // 如果是 '一' 让他在0的位置下降，不然会很慢出现
      if (this.currentModel[0].row == 0 && this.currentModel[0].col == 0) {
        this.currentY = 0;

      }

      // 创建当前使用的模型
      for (let key in this.currentModel) {
        // let divEle = document.createElement('span');
        let divEle = document.createElement('span');
        divEle.className = 'square';
        // divEle.setAttribute('ref', 'span');
        document.querySelector('.back').appendChild(divEle);

      }

      this.locationBlocks();

      if (this.changeCss) {
        // 黑暗模式下，消除一行奖励自己放置砖块一次,pass
        // if (!this.$store.state.flag) {
        //   this.autoDown(2000000);
        // }
        // else {
        this.autoDown(this.speed);
        // }
      }
      else {
        this.autoDown(this.speed);
      }

    },
    //  旋转模型
    rotate() {
      if (this.$store.state.speed == 100000) {
        return;
      }
      // 旋转后的行 = 旋转前的列
      // 旋转后的列 = 3- 旋转前的行
      let cloneCurrentModel = _.cloneDeep(this.currentModel);
      // 遍历
      for (let key in cloneCurrentModel) {
        let blockModel = cloneCurrentModel[key];
        let temp = blockModel.row;
        blockModel.row = blockModel.col;
        blockModel.col = 3 - temp;
      }
      // 如果旋转之后发生碰碰撞，不旋转
      if (this.isMeet(this.currentX, this.currentY, cloneCurrentModel)) {
        return;
      }
      // 接受了这次旋转
      if (this.changeCss) {
        music_gm.rotate();
      }
      else {
        music.rotate();
      }
      this.currentModel = cloneCurrentModel;
      this.locationBlocks();
    },
    // 判断模型之间的触碰问题
    // X,Y表示16宫格《将要》移动到的位置
    // model表示当前模型数据源 《将要》 完成的变化
    isMeet(x, y, model) {
      // 存存在返回 true 表示将要移动到的位置会发生触碰， 否则返回 false
      for (let i in model) {
        let blockModel = model[i];
        if (this.fixedBlocks[(y + blockModel.row) + '_' + (x + blockModel.col)]) {
          return true;
        }
      }
      return false;
    },
    // 控制模型只能在 容器中移动
    checkBound() {
      let leftBound = 0,
        rightBound = this.COL_COUNT,
        bottomBound = this.ROW_COUNT;
      // 超出边界后退一格
      for (let key in this.currentModel) {
        // 数据
        let blockModel = this.currentModel[key];
        // 左侧越界
        if ((blockModel.col + this.currentX) < leftBound) this.currentX++;
        // 右侧越界
        if ((blockModel.col + this.currentX) >= rightBound) this.currentX--;
        // 下侧越界
        if ((blockModel.row + this.currentY) >= bottomBound) {
          this.currentY--;
          this.fixedBottomModel();
        }
      }

    },
    locationBlocks() {
      // 判断越界
      this.checkBound();
      

      // 1.拿到所有的块元素
      let eles = document.getElementsByClassName('square');
      for (let i = 0; i < eles.length; i++) {
        let activityModelEle = eles[i];
        // 2.找到每个块元素对应的数据(行列)
        let blockModel = this.currentModel[i];
        // 3.根据每个块元素对应的数据来指定块元素的位置
        // 每个块元素的位置由两个值确定：1、16宫格所在的位置2、块元素在16宫格中的位置
        activityModelEle.style.top = (this.currentY + blockModel.row) * this.step + 'px';
        activityModelEle.style.left = (this.currentX + blockModel.col) * this.step + 'px';
      }
    },
    // 固定模型在底部
    fixedBottomModel() {
      // 碰到短暂修改样式
      // 让模型不可以在移动
      let eles = document.getElementsByClassName('square');
      for (let i = eles.length - 1; i >= 0; i--) {
        // 拿到每个块元素
        let activityModelEle = eles[i];
        activityModelEle.className = 'fixed_model_tem';
        // activityModelEle.className = 'fixed_model';
        setTimeout(() => {
          // activityModelEle.style.backgroundColor = '#879372';
          activityModelEle.className = 'fixed_model_tow';

        }, 100);
        // 把该块元素放入变量中
        let blockModel = this.currentModel[i];
        this.fixedBlocks[(this.currentY + blockModel.row) + '_' + (this.currentX + blockModel.col)]
          = activityModelEle;
      }

      if (!this.isGameOver()) {
        // 如果游戏已经结束了，那么就不加分
        this.$store.commit('addScore', 10);
        this.$store.commit('splitsum');
        // console.log(this.$store.state.score);
      }

      // 消除铺满的行
      // this.$store.commit('ansynflag', 0);
      this.isRemoveLine();
      // 创建新模型
      this.createModel();
    },

    // 是否铺满一行
    isRemoveLine() {
      // 遍历所有行
      // 计数器,记录每一行存在的块元素的数量
      for (var i = 0; i < this.ROW_COUNT; i++) {
        let count = 0;
        // 遍历所有列
        for (var j = 0; j < this.COL_COUNT; j++) {
          //  判断改行该列是否存在块元素
          if (this.fixedBlocks[i + '_' + j]) {
            count++;
          }
        }

        if (count === this.COL_COUNT) {
          // 动画过程中不允许创造,修改锁为false
          this.$store.commit('ansynflag', false);
          // 如果每一行中存在的块元素数量 === 列数，表示一行中每一列都存在块元素
          // 删除该行
          // 遍历铺满的行，做动画
          for (let g = 0; g < this.COL_COUNT; g++) {
            let activityModelEle = this.fixedBlocks[i + '_' + g];
            setTimeout(() => {
              activityModelEle.className = 'fixed_model_tem';
            }, 100);
            setTimeout(() => {
              activityModelEle.className = 'fixed_model_two';
            }, 200);
            setTimeout(() => {
              activityModelEle.className = 'fixed_model_tem';
            }, 300);
            setTimeout(() => {
              activityModelEle.className = 'fixed_model_two';
            }, 400);
            setTimeout(() => {
              activityModelEle.className = 'fixed_model_tem';
            }, 500);
            setTimeout(() => {
              activityModelEle.className = 'fixed_model_two';
            }, 600);
          }

          let tem = i;
          setTimeout(() => {
            // 动画完成允许创造，修改锁true
            this.$store.commit('ansynflag', true);
            this.removeLine(tem);
          }, 700);
          this.$store.commit('addScore', 100);
          // this.$store.dispatch('actionsasyncflag', 100);
          if (this.changeCss) {
            music_gm.clear();
          }
          else {
            music.clear();
          }
        }
      }
      if (Error) {
        // 屏蔽黑暗模式的错误
        window.onerror = () => true;
      }
    },
    removeLine(line) {
      // console.log(line);
      for (var i = 0; i < this.COL_COUNT; i++) {
        //   // 1 删除该行中所有的块元素
        document.getElementById('back').removeChild(this.fixedBlocks[line + '_' + i]);
        //   // 2 删除该行中所有块元素的数据源
        this.fixedBlocks[line + '_' + i] = null;
      }
      //当前消除行+1
      this.$store.commit('rmRowsumAdd');
      this.downLine(line);

    },
    // 让指定行之上的块元素下落
    downLine(line) {
      // 让指定行之上的所有行中的每一列的块元素，向下移动 1 个步长
      // 遍历指定行之上的所有行
      for (var i = (line - 1); i >= 0; i--) {
        // 这些行中每一列元素
        for (var j = 0; j < this.COL_COUNT; j++) {
          // 如果当前列没有数据进入下一次循环
          if (!this.fixedBlocks[i + '_' + j]) continue;
          // 如果当前行的当前列存在块元素的话
          // 1、平移数据，把当前行的数据给下一行
          this.fixedBlocks[(i + 1) + '_' + j] = this.fixedBlocks[i + '_' + j];
          // 2、平移元素，让当前行的元素到下一行
          this.fixedBlocks[(i + 1) + '_' + j].style.top = (i + 1) * this.step + 'px';
          // 3、清理掉平移之前的数据
          this.fixedBlocks[i + '_' + j] = null;
          // this.fixedBlocks[(i + 1) + '_' + j].style.top = (i + 1) * this.setp + 'px';
        }
      }
    },
    // 让模型自动下落
    autoDown(speed) {

      if (this.mInterval) {
        clearInterval(this.mInterval);
      }
      this.mInterval = setInterval(() => {
        this.move(0, 1, false);
      }, speed);
    },
    // 判断游戏结束
    isGameOver() {
      // 当第0行存在块元素表示游戏结束
      for (var i = 0; i < this.COL_COUNT; i++) {
        if (this.fixedBlocks['0_' + i]) {
          // console.log(i);
          return true;
        }
      }
    },
    gameOver() {
      // 1、停止定时器
      if (this.mInterval) {
        clearInterval(this.mInterval);
      }
      if (this.changeCss) {
        music_gm.gameover();
      }
      else {
        music.gameover();
      }

      this.$store.commit('musicState');
      // 存储分数,如果获得分数大于之前的最大分数，存入
      if (localStorage.getItem('maxScore') < this.$store.state.score) {
        localStorage.setItem('maxScore', this.$store.state.score);
      }

      // 2、弹出对话框，告诉用户游戏结束了
      // this.gameOver = true;
      // alert('游戏结束');
    },
    keyUp() {
      if (this.top) {
        return;
      }
      this.rotate();
      this.top = setInterval(() => {
        this.rotate();
      }, 200);
    },
    keyDown() {
      if (this.down) {
        return;
      }
      this.move(0, 1, true);
      this.down = setInterval(() => {
        this.move(0, 1, true);
      }, 100);
    },
    keyLeft() {
      // 防止按住左键一直触发定时器
      if (this.left) {
        return;
      }
      this.move(-1, 0, true);
      this.left = setInterval(() => {
        this.move(-1, 0, true);
      }, this.droptime);
    },
    keyRight() {
      if (this.right) {
        return;
      }
      this.move(1, 0, true);
      this.right = setInterval(() => {
        this.move(1, 0, true);
      }, this.droptime);
    },
    keySpace() {
      if (this.isGameOver()) {
        this.gameOver();
        return;
      }
      if (this.$store.state.speed == 100000 || this.time) {
        return;

      }
      this.autoDown(10);
      var dp = document.querySelector('.rect');
      dp.className = 'rect drop';

      setTimeout(() => {
        if (this.changeCss) {
          music_gm.fall();
        }
        else {
          music.fall();
        }
        // dp.className = 'rect';
      }, 40);

      this.time = setInterval(() => {
        this.autoDown(10);
        dp.className = 'rect drop';

        if (this.changeCss) {
          music_gm.fall();
        }
        else {
          music.fall();
        }

      }, 250);
    },
    eventCleanTimer() {
      document.addEventListener('keyup', e => {
        if (this.left && e.code == 'ArrowLeft') {
          clearInterval(this.left);
          this.left = null;
        }
        if (this.down && e.code == 'ArrowDown') {
          clearInterval(this.down);
          this.down = null;
        }
        if (this.right && e.code == 'ArrowRight') {
          clearInterval(this.right);
          this.right = null;
        }
        if (this.top && e.code == 'ArrowUp') {
          // this.move(0, -1);
          clearInterval(this.top);
          this.top = null;
        }
        if (this.time && e.code == 'Space') {

          clearTimeout(this.time);
          var dp = document.querySelector('.rect');
          dp.className = 'rect';
          this.time = null;

        }
        if (e.code == 'KeyR') {
          // var eles = document.getElementById('back');
          // console.log(eles[2]);

          // 讲对象转换为数组
          // var arr = [];

          // for (let i in this.fixedBlocks) {

          //   arr.push(i);        //key
          // }
          // var eles = document.getElementById('back');
          // arr.splice(1, arr.length);
          // this.$store.commit('fixedBlocksChange',arr);

          // arr.forEach((val, index) => {
          // console.log(val);
          // console.log(index);

          // });

          // for (var i = 0; i < this.ROW_COUNT; i++) {
          //   for (var j = 0; j < this.COL_COUNT; j++) {
          //     // document.getElementById('back').push
          //     // 1 删除该行中所有的块元素
          //     if(document.getElementById('back')){
          //       document.getElementById('back').removeChild(this.fixedBlocks[i + '_' + j]);
          //     }
          //     // // 2 删除该行中所有块元素的数据源
          //     // this.fixedBlocks[i + '_' + j] = null;
          //   }
          // }
        }
      });


    }
  },

  mounted() {


    // 判断是否空对象
    // console.log(JSON.stringify(this.nextModel) == '{}');
    // 暂停，监听到按键事件开始游戏
    window.addEventListener('keydown', (e) => {
      // 暂停中可以通过游戏按键继续游戏
      if (this.stop && e.code == 'ArrowUp' ||
        this.stop && e.code == 'ArrowDown' ||
        this.stop && e.code == 'ArrowLeft' ||
        this.stop && e.code == 'ArrowRight' ||
        this.stop && e.code == 'Space') {

        this.$store.commit('downStop');

      }
      if (this.gameplay) {
        return;
      }
      else if (e.code == 'ArrowUp'
        || e.code == 'ArrowDown'
        || e.code == 'ArrowLeft'
        || e.code == 'ArrowRight'
        || e.code == 'Space') {
        this.$store.commit('gameplay');
      }
    });


    this.createModel();
    this.key();

    var ze = /b\s/;

    // 不会封装，只能拿下来
    var btn = document.querySelectorAll('i');
    for (var i = 0; i < btn.length; i++) {
      let currentBtn = i;

      // console.log(btn[currentBtn].parentNode.className);
      // console.log(ze.test(btn[currentBtn].parentNode.className));   //true

      // 如果父亲的类名存在b b,则是点击了按钮
      btn[currentBtn].addEventListener('mousedown', (e) => {
        // 掉落
        this.$store.commit('gameplay');

        if (btn[currentBtn].parentNode.className.indexOf('b b') !== -1) {
          this.keySpace();

        }

        // 旋转
        if (btn[currentBtn].parentNode.className.indexOf('r1') !== -1) {
          this.keyUp();
        }

        // 左移
        if (btn[currentBtn].parentNode.className.indexOf('r2') !== -1) {
          this.keyLeft();
        }
        // 右移
        if (btn[currentBtn].parentNode.className.indexOf('r3') !== -1) {
          this.keyRight();

        }
        // 下移
        if (btn[currentBtn].parentNode.className.indexOf('r4') !== -1) {
          this.keyDown();
        }

      });


      document.addEventListener('mouseup', e => {
        // 掉落
        if (btn[currentBtn].parentNode.className.indexOf('b b') !== -1) {
          clearTimeout(this.time);
          var dp = document.querySelector('.rect');
          dp.className = 'rect';
          this.time = null;
        }
        // 旋转
        if (btn[currentBtn].parentNode.className.indexOf('r1') !== -1) {
          clearInterval(this.top);
          this.top = null;
        }
        // 坐移
        if (btn[currentBtn].parentNode.className.indexOf('r2') !== -1) {
          clearInterval(this.left);
          this.left = null;
        }
        // 右移
        if (btn[currentBtn].parentNode.className.indexOf('r3') !== -1) {
          clearInterval(this.right);
          this.right = null;
        }
        // 下移
        if (btn[currentBtn].parentNode.className.indexOf('r4') !== -1) {
          clearInterval(this.down);
          this.down = null;
        }
      });
    }
  },


};